Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GL_TEXTURE_RECTANGLE texture target support #997

Merged
merged 4 commits into from
Mar 30, 2017

Conversation

JerryShih
Copy link
Contributor

@JerryShih JerryShih commented Mar 21, 2017

@glennw @kvark @nical @sotaroikeda
The hardware video decoder in mac platform is usually decoding the video content into MacIOSurface. The MacIOSurface could just map to an GL_TEXTURE_RECTANGLE gl texture without any uploading. That's good for video playing.
These patches try to add a new type of external gl rect image and its corresponding shader.


This change is Reviewable

@JerryShih
Copy link
Contributor Author

There is still a the black screen when I pass an GL_TEXTURE_RECTANGLE gl texture to WR. I have no idea why I can't see the video content. Maybe @nical @kvark @glennw could point out the error for my patch.

@bors-servo
Copy link
Contributor

☔ The latest upstream changes (presumably #995) made this pull request unmergeable. Please resolve the merge conflicts.

Copy link
Contributor Author

@JerryShih JerryShih left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0ce9f97:

This commit changes the enum ImageData and SourceTexture def.
0ce9f97#diff-9aae73cdde1c142339d62fa040c56ec1R86

0ce9f97#diff-d92392172ea565b8624a34bb15391bccR52

Then we could pass the different external gl handle around the rendering path. Then, we could get the image type in SourceSurface to select the correct shader(We are trying to handle TEXTURE_2D and TEXTURE_RECT).

uniform sampler2D sColor0;
uniform sampler2D sColor1;
uniform sampler2D sColor2;
#else
uniform sampler2DRect sColor0;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

macIOSurface should use sampler2DRect


alpha = alpha * float(all(bvec2(step(position_in_tile, vStretchSize))));

oFragColor = vec4(alpha) * texture(sColor0, st);
Copy link
Contributor Author

@JerryShih JerryShih Mar 21, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

textureLod doesn't support Sample2DRect. Use texture() instead.
And the range of each st components are not in [0.0, 1.0]. They are in [0, texture_size.width] and [0, texture_size.height].

@@ -659,6 +662,13 @@ impl Renderer {
options.precache_shaders)
};

let ps_image_rect = try!{
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I add a new shader for textureRect. We could also merge this back to the original image shader. I don't like too much "#ifdef" in the code.

SourceTexture::External(ext_image) => {
match ext_image.image_type {
ExternalImageType::Texture2DHandle => AlphaBatchKind::Image,
ExternalImageType::TextureRectHandle => AlphaBatchKind::ImageRect,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When we have "ExternalImageType::TextureRectHandle", use ImageRect shader for this type.

@nical
Copy link
Contributor

nical commented Mar 21, 2017

For reference, Gecko appears to be using texture2DRect and sampler2DRect:
https://searchfox.org/mozilla-central/rev/ee7cfd05d7d9f83b017dd54c2052a2ec19cbd48b/gfx/layers/opengl/OGLShaderProgram.cpp#368

I would prefer to not add extra shader source files for this (and just #define our way into implementing this)

@kvark
Copy link
Member

kvark commented Mar 21, 2017

I'd like to avoid first-class support for texture rectangles in WR. This concept is not supported outside of GL land, so it would make it more difficult to introduce more graphics backends. Instead, I'd like to see as minimal hack as possible to support MacIOSurface's limitations.

@nical
Copy link
Contributor

nical commented Mar 21, 2017

We don't have a choice on OSX as it's the only way to render hardware accelerated video frames as far as I know.

@kvark
Copy link
Member

kvark commented Mar 21, 2017

@nical yes, that's why I said let's hack this in. Doing a compile switch for the shaders is certainly a smaller hack then exposing the rectangles as a valid texture type.

@nical
Copy link
Contributor

nical commented Mar 21, 2017

Ah yes, I agree. And not such a bad hack since the only things that change are the uniform sampler definition and sampling function name. We already have compile time switches for bigger things like transforms.
Even for the rest of the code I'm sure we can simplify things a fair amount (just need to pass enough information to select the proper texture target).

@JerryShih
Copy link
Contributor Author

@kvark @nical

I'd like to avoid first-class support for texture rectangles in WR. This concept is not supported outside of GL land, so it would make it more difficult to introduce more graphics backends.

Yes, this concept is not supported outside of GL land. But why this is the problem if we try to have more graphics backends? We could just have a panic hint for the new backend if we try to use the non-supported TextureRectHandle feature.

And how could we recognize the current usage for texture2d or textureRect without adding the new type of externalImage? That information is required to switch the different shaders for texture2d and textureRect. We might have both usage of texture2d or textureRect at mac platform.

So, I extend the external image type into:

+pub enum ExternalImageType {
+    Texture2DHandle,    // gl TEXTURE_2D handle
+    TextureRectHandle,  // gl TEXTURE_RECT handle
+    ExternalBuffer,
+}

0ce9f97#diff-9aae73cdde1c142339d62fa040c56ec1

Most of changes are for these new types updating.

@kvark
Copy link
Member

kvark commented Mar 22, 2017

@JerryShih yeah, having ExternalImageType::TextureRectHandle case for this seems to be unavoidable.

@JerryShih
Copy link
Contributor Author

@kvark @nical

@JerryShih yeah, having ExternalImageType::TextureRectHandle case for this seems to be unavoidable.

Thanks, I will keep working base on the new type "ExternalImageType::TextureRectHandle".

The ps_image_rect and ps_image shader will be merged together. And I will use a feature "#ifdef" to switch the different functionality(texture2D and textureRect).

@bors-servo
Copy link
Contributor

☔ The latest upstream changes (presumably #1003) made this pull request unmergeable. Please resolve the merge conflicts.

@bors-servo
Copy link
Contributor

☔ The latest upstream changes (presumably #966) made this pull request unmergeable. Please resolve the merge conflicts.

panic!("External texture handle should not go through texture_cache.");
}
ExternalImageType::ExternalBuffer => {
let update_op = TextureUpdate {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

panic!("External texture handle should not go through texture_cache.");
}
ExternalImageType::ExternalBuffer => {
let update_op = TextureUpdate {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -651,6 +674,87 @@ impl ResourceCache {
}
}
}
fn update_texture_cache(cached_images: &mut ResourceClassCache<ImageRequest, CachedImageInfo>,
Copy link
Contributor Author

@JerryShih JerryShih Mar 27, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function is extracted from:
b4e91e1#diff-77cbdf7ba9ebae81feb38a64c21b8454L669
Since there are some "self" mutable borrow problem, this update_texture_cache() becomes static function.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: may look better if it's not static
What borrow problems did you encounter? Maybe we can work around them in a cleaner way.

texture_cache_id: image_id,
epoch: image_template.epoch,
});
ExternalImageType::ExternalBuffer => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We only call update_texture_cache for ExternalBuffer, Raw and Blob image.

ImageData::ExternalHandle(id) => Some(id),
// raw and externalBuffer are all use resource_cache.
ImageData::Raw(..) | ImageData::ExternalBuffer(..) | ImageData::Blob(..) => None,
let external_image = match image_template.data {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Texture2DHandle, TextureRectHandle => some(ext_image)
Raw, Blob, ExternalBuffer => None

@JerryShih
Copy link
Contributor Author

@kvark @nical @glennw
The image and image_shader are merged together now. Then, we could set the TEXTURE_RECT_FEATURE flag to work for TEXTURE_RECT type.

let ps_image_rect = try!{
    PrimitiveShader::new("ps_image",
                         &mut device,
                         &[ TEXTURE_RECT_FEATURE ],
                         options.precache_shaders)
};

Could you please take a look at this?

Copy link
Member

@kvark kvark left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found no major issues, but got a few things to address preferably.

vec2 st = vTextureOffset + ((position_in_tile / vStretchSize) * vTextureSize);
st = clamp(st, vStRect.xy, vStRect.zw);

alpha = alpha * float(all(bvec2(step(position_in_tile, vStretchSize))));

#ifndef WR_FEATURE_TEXTURE_RECT
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer having ifdef path instead of ifndef

@@ -2,10 +2,13 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

// If this is in WR_FEATURE_TEXTURE_RECT mode, the rect and size use non-normalized
// texture coordinates. Otherwise, it's use normalized texture coordinates. Please
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix it's use -> it uses

// vUv will contain how many times this image has wrapped around the image size.
#ifndef WR_FEATURE_TEXTURE_RECT
vec2 texture_size = vec2(textureSize(sColor0, 0));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could be less of a code change if just texture_size is branched out, and the rest of the code is uniform

ExternalImageType::Texture2DHandle => TextureTarget::Default,
ExternalImageType::TextureRectHandle => TextureTarget::Rect,
_ => {
panic!("Not a suitable image type.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: actually include the type in the message

@@ -651,6 +674,87 @@ impl ResourceCache {
}
}
}
fn update_texture_cache(cached_images: &mut ResourceClassCache<ImageRequest, CachedImageInfo>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: add new line before the function

@@ -651,6 +674,87 @@ impl ResourceCache {
}
}
}
fn update_texture_cache(cached_images: &mut ResourceClassCache<ImageRequest, CachedImageInfo>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: may look better if it's not static
What borrow problems did you encounter? Maybe we can work around them in a cleaner way.

@JerryShih
Copy link
Contributor Author

Review status: 0 of 14 files reviewed at latest revision, 9 unresolved discussions.


webrender/res/ps_image.fs.glsl, line 32 at r3 (raw file):

Previously, kvark (Dzmitry Malyshau) wrote…

I'd prefer having ifdef path instead of ifndef

Done.


webrender/res/ps_image.glsl, line 6 at r3 (raw file):

Previously, kvark (Dzmitry Malyshau) wrote…

fix it's use -> it uses

Done.


webrender/res/ps_image.vs.glsl, line 37 at r3 (raw file):

Previously, kvark (Dzmitry Malyshau) wrote…

could be less of a code change if just texture_size is branched out, and the rest of the code is uniform

Done.


webrender/src/renderer.rs, line 1673 at r3 (raw file):

Previously, kvark (Dzmitry Malyshau) wrote…

nit: actually include the type in the message

Done.


webrender/src/resource_cache.rs, line 677 at r3 (raw file):

Previously, kvark (Dzmitry Malyshau) wrote…

nit: add new line before the function

Done.


Comments from Reviewable

@JerryShih
Copy link
Contributor Author

fn update_texture_cache2(&mut self) {
    println!("test");
}

fn finalize_image_request(&mut self,
                          request: ImageRequest,
                          image_data: Option<ImageData>,
                          texture_cache_profile: &mut TextureCacheProfileCounters) {
    let image_template = self.image_templates.get_mut(&request.key).unwrap();
    let image_data = image_data.unwrap_or_else(||{
        image_template.data.clone()
    });

    match image_template.data {
        ImageData::External(ext_image) => {
            match ext_image.image_type {
                ExternalImageType::Texture2DHandle |
                ExternalImageType::TextureRectHandle => {
                    // external handle doesn't need to update the texture_cache.
                }
                ExternalImageType::ExternalBuffer => {
                    self.update_texture_cache2();   // use member function

                    ResourceCache::update_texture_cache(&mut self.cached_images,
                                                        &mut self.texture_cache,
                                                        self.current_frame_id,
                                                        &request,
                                                        image_template,
                                                        image_data,
                                                        texture_cache_profile);
                }
            }
        }
        ImageData::Raw(..) | ImageData::Blob(..) => {
            ResourceCache::update_texture_cache(&mut self.cached_images,
                                                &mut self.texture_cache,
                                                self.current_frame_id,
                                                &request,
                                                image_template,
                                                image_data,
                                                texture_cache_profile);
        }
    }
}

The error message:

error[E0499]: cannot borrow `*self` as mutable more than once at a time
   --> src/resource_cache.rs:781:25
    |
768 |         let image_template = self.image_templates.get_mut(&request.key).unwrap();
    |                              -------------------- first mutable borrow occurs here
...
781 |                         self.update_texture_cache2();
    |                         ^^^^ second mutable borrow occurs here
...
803 |     }
    |     - first borrow ends here

Review status: 0 of 14 files reviewed at latest revision, 9 unresolved discussions.


Comments from Reviewable

@bors-servo
Copy link
Contributor

☔ The latest upstream changes (presumably #1009) made this pull request unmergeable. Please resolve the merge conflicts.

@kvark
Copy link
Member

kvark commented Mar 28, 2017

@JerryShih
We can work around it by doing:

let (old_data, new_data) = {
    let image_template = self.image_templates.get_mut(&request.key).unwrap();
    let new_data = image_data.unwrap_or_else(||{
        image_template.data.clone()
    });
    (image_template.data.clone(), new_data)
};

match old_data {
...
}

This would contain the borrow of self.image_templates within a small scope and allow borrowing self for method calls inside the match arms.

@JerryShih
Copy link
Contributor Author

@kvark

let (old_data, new_data) = {
    let image_template = self.image_templates.get_mut(&request.key).unwrap();
    let new_data = image_data.unwrap_or_else(||{
        image_template.data.clone()
    });
    (image_template.data.clone(), new_data)
};

match old_data {
...
}

Sorry, my test code doesn't show all detail. We should not use the cloned image_template here. It will be updated in update_texture_cache().

fn update_texture_cache(cached_images: &mut ResourceClassCache<ImageRequest, CachedImageInfo>,
texture_cache: &mut TextureCache,
current_frame_id: FrameId,
fn update_texture_cache(&mut self,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is another version of update_texture_cache(). This version spends one more "image_templates" hash table lookup, but it turns to a member function.
I still prefer the static function one.

@JerryShih
Copy link
Contributor Author

r? @kvark
5da747c

@bors-servo
Copy link
Contributor

☔ The latest upstream changes (presumably #1004) made this pull request unmergeable. Please resolve the merge conflicts.

@JerryShih
Copy link
Contributor Author

Sorry, rebase again.

@kvark
Copy link
Member

kvark commented Mar 29, 2017

Thanks @JerryShih !
Do you mind squashing the commits a little before merging?

@JerryShih
Copy link
Contributor Author

@kvark
I don't know why the comments in reviewable are not shown in github. The concern of my last version is the one additional hash table lookup.

Here is another version of update_texture_cache(). This version spends one more "image_templates" hash table lookup, but it turns to a member function.
I still prefer the static function one.

@JerryShih
Copy link
Contributor Author

@kvark
If ths is not a problem, here are the squashed patches.

I don't know why the comments in reviewable are not shown in github. The concern of my last version is the one additional hash table lookup.

Here is another version of update_texture_cache(). This version spends one more "image_templates" hash table lookup, but it turns to a member function.
I still prefer the static function one.

@kvark
Copy link
Member

kvark commented Mar 30, 2017

@JerryShih I see, thanks. The double lookup should be fine (until we get deeper into the optimization stage), given that the relevant hashmap cell is already in the cache by that time.
@bors-servo r+

@bors-servo
Copy link
Contributor

📌 Commit bbfefcc has been approved by kvark

@bors-servo
Copy link
Contributor

⌛ Testing commit bbfefcc with merge 9800670...

bors-servo pushed a commit that referenced this pull request Mar 30, 2017
GL_TEXTURE_RECTANGLE texture target support

@glennw @kvark @nical @sotaroikeda
The hardware video decoder in mac platform is usually decoding the video content into MacIOSurface. The MacIOSurface could just map to  an GL_TEXTURE_RECTANGLE gl texture without any uploading. That's good for video playing.
These patches try to add a new type of external gl rect image and its corresponding shader.

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/webrender/997)
<!-- Reviewable:end -->
@bors-servo
Copy link
Contributor

☀️ Test successful - status-travis
Approved by: kvark
Pushing 9800670 to master...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants